package modbus

import (
	"encoding/binary"
	"errors"
	"fmt"
	"math"
	"net"
	"strings"
	"time"
)

// 网关协议扩展功能码常量
const (
	// 网关协议功能码
	FuncCodeGatewayReadDataRecords  = 0x50 // 读数据记录
	FuncCodeGatewayReadCurrentData  = 0x51 // 读当前数据
	FuncCodeGatewayWriteSubDevParam = 0x52 // 写子设备参数
	FuncCodeGatewayWriteGWParam     = 0x53 // 写网关参数
	FuncCodeGatewayReadSubDevParam  = 0x54 // 读子设备参数
	FuncCodeGatewayReadGWParam      = 0x55 // 读网关参数
)

// 网关协议异常码
const (
	ExceptionCodeGatewayReadDataError    = 0x80 // 读数据异常
	ExceptionCodeGatewayReadDataError2   = 0x81 // 读数据异常（备用）
	ExceptionCodeGatewayWriteSubDevError = 0x82 // 写子设备参数异常
	ExceptionCodeGatewayWriteGWError     = 0x83 // 写网关参数异常
	ExceptionCodeGatewayReadSubDevError  = 0x84 // 读子设备参数异常
	ExceptionCodeGatewayReadGWError      = 0x85 // 读网关参数异常
)

// 压力单位枚举
const (
	PressureUnitMbar  = 0x01 // 毫巴
	PressureUnitBar   = 0x02 // 巴
	PressureUnitPsi   = 0x03 // 磅力/平方英寸
	PressureUnitPa    = 0x04 // 帕斯卡
	PressureUnitKPa   = 0x05 // 千帕斯卡
	PressureUnitMPa   = 0x06 // 兆帕斯卡
	PressureUnitMmH2O = 0x07 // 毫米水柱
	PressureUnitMH2O  = 0x08 // 米水柱
	PressureUnitFtH2O = 0x09 // 英尺水柱
	PressureUnitInH2O = 0x0A // 英寸水柱
)

// 变送器参数地址
const (
	SubDevParamPressureUnit       = 0x0001 // 压力单位
	SubDevParamLCDDecimalPlaces   = 0x0002 // 液晶显示小数位
	SubDevParamTransmitterAddr    = 0x0003 // 变送器地址
	SubDevParamLanguage           = 0x0004 // 语言
	SubDevParamLCDRotation        = 0x0005 // 液晶旋转
	SubDevParamLCDDisplayStatus   = 0x0006 // 液晶显示状态
	SubDevParamBacklightTime      = 0x0007 // 背光显示时间
	SubDevParamLCDPassword        = 0x0008 // 液晶操作密码
	SubDevParamDataReportInterval = 0x0009 // 数据上报间隔
	SubDevParamZeroReset          = 0x000A // 零点清零
)

// 网关参数地址
const (
	GatewayParamTime          = 0x0001 // 时间（Unix时间戳）
	GatewayParamRS485Baudrate = 0x0002 // RS485波特率
	GatewayParamRS485Address  = 0x0003 // RS485地址
	GatewayParamBacklightTime = 0x0004 // 背光显示时间
)

// 数据记录结构（16字节）
type DataRecord struct {
	Pressure         float32 // 压力值（4字节，大端浮点数）
	PressureUnit     uint8   // 压力单位（1字节）
	BatteryLevel     uint8   // 电池电量（1字节，0-100%）
	ConnectionStatus uint8   // 连接状态（1字节，0=断开，1=连接）
	SignalLevel      uint8   // 信号等级（1字节，0-5级）
	Liangcheng       uint8   // 量程 1:70Mp  2:100Mp
	Reserved         [3]byte // 预留字段（4字节）
	Timestamp        uint32  // 数据采集时间（4字节，Unix时间戳，大端）秒级
}

// ToBytes 转换为字节数组
func (dr *DataRecord) ToBytes() []byte {
	data := make([]byte, 16)

	// 压力值（大端浮点数）
	binary.BigEndian.PutUint32(data[0:4], math.Float32bits(dr.Pressure))

	// 其他字段
	data[4] = dr.PressureUnit
	data[5] = dr.BatteryLevel
	data[6] = dr.ConnectionStatus
	data[7] = dr.SignalLevel
	data[8] = dr.Liangcheng // 量程字段

	// 预留字段（3字节）
	copy(data[9:12], dr.Reserved[:])

	// 时间戳（大端）
	binary.BigEndian.PutUint32(data[12:16], dr.Timestamp)

	return data
}

// NewDataRecordFromBytes 从字节数组创建数据记录
func NewDataRecordFromBytes(data []byte) (*DataRecord, error) {
	if len(data) != 16 {
		return nil, errors.New("invalid data record length")
	}

	dr := &DataRecord{}

	// 压力值（大端浮点数）
	pressureBits := binary.BigEndian.Uint32(data[0:4])
	dr.Pressure = math.Float32frombits(pressureBits)

	// 其他字段
	dr.PressureUnit = data[4]
	dr.BatteryLevel = data[5]
	dr.ConnectionStatus = data[6]
	dr.SignalLevel = data[7]
	dr.Liangcheng = data[8] // 量程字段

	// 预留字段（3字节）
	copy(dr.Reserved[:], data[9:12])

	// 时间戳（大端）
	dr.Timestamp = binary.BigEndian.Uint32(data[12:16])

	return dr, nil
}

// GetPressureUnitName 获取压力单位名称
func GetPressureUnitName(unit uint8) string {
	switch unit {
	case PressureUnitMbar:
		return "mbar"
	case PressureUnitBar:
		return "bar"
	case PressureUnitPsi:
		return "psi"
	case PressureUnitPa:
		return "Pa"
	case PressureUnitKPa:
		return "kPa"
	case PressureUnitMPa:
		return "MPa"
	case PressureUnitMmH2O:
		return "mmH2O"
	case PressureUnitMH2O:
		return "mH2O"
	case PressureUnitFtH2O:
		return "ftH2O"
	case PressureUnitInH2O:
		return "inH2O"
	default:
		return "unknown"
	}
}

// GetLiangchengName 获取量程名称
func GetLiangchengName(liangcheng uint8) string {
	switch liangcheng {
	case 1:
		return "70MPa"
	case 2:
		return "100MPa"
	default:
		return "unknown"
	}
}

// GatewayRequest 网关协议请求结构
type GatewayRequest struct {
	FuncCode byte   // 功能码
	SlaveID  byte   // 设备ID
	Data     []byte // 请求数据
}

// GatewayResponse 网关协议响应结构
type GatewayResponse struct {
	FuncCode byte   // 功能码
	SlaveID  byte   // 设备ID
	Data     []byte // 响应数据
}

// sendGatewayRequest 统一的网关协议ADU发送函数
// 自动处理MBAP头构造、重试机制、错误处理等
func (sf *client) sendGatewayRequest(request *GatewayRequest) (*GatewayResponse, GatewayRawData, error) {
	const maxRetries = 3
	const retryDelay = 100 * time.Millisecond

	for attempt := 1; attempt <= maxRetries; attempt++ {
		// 构造完整的ADU请求：MBAP头(7字节) + PDU(Unit ID + 功能码 + 数据)
		// 注意：PDU长度 = Unit ID(1) + 功能码(1) + 数据长度
		pduLength := 1 + 1 + len(request.Data) // Unit ID(1) + 功能码(1) + 数据长度
		aduRequest := make([]byte, 6+pduLength)

		// MBAP头（7字节）
		// 使用递增的事务ID，与尝试次数结合确保唯一性
		// 由于我们直接使用 SendRawFrame，需要手动管理事务ID
		// 使用时间戳 + 尝试次数保证每次请求的事务ID不同
		transactionID := uint16(time.Now().UnixNano()&0xFFFF) + uint16(attempt)
		aduRequest[0] = byte(transactionID >> 8)   // 事务ID高字节
		aduRequest[1] = byte(transactionID & 0xFF) // 事务ID低字节
		aduRequest[2] = 0x00                       // 协议ID高字节（固定0x0000）
		aduRequest[3] = 0x00                       // 协议ID低字节
		aduRequest[4] = byte(pduLength >> 8)       // PDU长度高字节
		aduRequest[5] = byte(pduLength & 0xFF)     // PDU长度低字节
		aduRequest[6] = request.SlaveID            // Unit ID

		// PDU（功能码 + 数据）
		aduRequest[7] = request.FuncCode   // 功能码
		copy(aduRequest[8:], request.Data) // 请求数据

		// fmt.Printf("[Attempt %d/%d] Gateway Request - FuncCode: 0x%02X, SlaveID: %d, TID: 0x%04X, ADU: [% x]\n",
		// 	attempt, maxRetries, request.FuncCode, request.SlaveID, transactionID, aduRequest)

		// 使用SendRawFrame发送完整的ADU
		aduResponse, err := sf.SendRawFrame(aduRequest)
		if err != nil {
			// 检查是否是可重试的错误
			if attempt < maxRetries && isRetryableError(err) {
				fmt.Printf("[Attempt %d/%d] Request failed with retryable error: %v, retrying in %v...\n",
					attempt, maxRetries, err, retryDelay)
				time.Sleep(retryDelay)
				continue
			}
			// 非可重试错误或已达到最大重试次数
			return nil, GatewayRawData{RequestADU: aduRequest, ResponseADU: nil, Error: err}, fmt.Errorf("gateway request failed after %d attempts, last error: %v", attempt, err)
		}

		// fmt.Printf("[Attempt %d/%d] Gateway Response ADU: [% x]\n", attempt, maxRetries, aduResponse)

		// 验证最小响应长度：MBAP头(6) + Unit ID(1) + 功能码(1) = 8字节
		if len(aduResponse) < 8 {
			if attempt < maxRetries {
				fmt.Printf("[Attempt %d/%d] Response too short: %d bytes, minimum 8, retrying in %v...\n",
					attempt, maxRetries, len(aduResponse), retryDelay)
				time.Sleep(retryDelay)
				continue
			}
			return nil, GatewayRawData{RequestADU: aduRequest, ResponseADU: nil, Error: err}, fmt.Errorf("gateway response too short after %d attempts", maxRetries)
		}

		// 验证MBAP头
		respTransactionID := binary.BigEndian.Uint16(aduResponse[0:2])
		respProtocolID := binary.BigEndian.Uint16(aduResponse[2:4])
		respLength := binary.BigEndian.Uint16(aduResponse[4:6])
		respUnitID := aduResponse[6]

		// 验证事务ID、协议ID和Unit ID
		if respTransactionID != transactionID {
			if attempt < maxRetries {
				fmt.Printf("[Attempt %d/%d] Transaction ID mismatch: got 0x%04X, expected 0x%04X, retrying in %v...\n",
					attempt, maxRetries, respTransactionID, transactionID, retryDelay)
				time.Sleep(retryDelay)
				continue
			}
			return nil, GatewayRawData{RequestADU: aduRequest, ResponseADU: aduResponse, Error: err}, fmt.Errorf("transaction ID mismatch after %d attempts: got 0x%04X, expected 0x%04X", maxRetries, respTransactionID, transactionID)
		}

		if respProtocolID != 0x0000 || respUnitID != request.SlaveID {
			if attempt < maxRetries {
				fmt.Printf("[Attempt %d/%d] MBAP header validation failed (ProtocolID: 0x%04X, UnitID: %d), retrying in %v...\n",
					attempt, maxRetries, respProtocolID, respUnitID, retryDelay)
				time.Sleep(retryDelay)
				continue
			}
			return nil, GatewayRawData{RequestADU: aduRequest, ResponseADU: nil, Error: err}, fmt.Errorf("MBAP header validation failed after %d attempts", maxRetries)
		}

		// 验证PDU长度
		// ADU结构：MBAP头前6字节 + PDU(包含Unit ID)
		expectedADULength := 6 + int(respLength)
		if len(aduResponse) != expectedADULength {
			if attempt < maxRetries {
				fmt.Printf("[Attempt %d/%d] ADU length mismatch: got %d, expected %d (MBAP(6) + PDU(%d)), retrying in %v...\n",
					attempt, maxRetries, len(aduResponse), expectedADULength, respLength, retryDelay)
				time.Sleep(retryDelay)
				continue
			}
			return nil, GatewayRawData{RequestADU: aduRequest, ResponseADU: nil, Error: err}, fmt.Errorf("ADU length validation failed after %d attempts", maxRetries)
		}

		// 验证PDU功能码
		respFuncCode := aduResponse[7]

		// 检查是否是异常响应（功能码最高位为1）
		if respFuncCode&0x80 != 0 {
			// 异常响应，PDU结构：Unit ID(1) + 功能码(1) + 异常码(1) = 3字节
			// ADU结构：MBAP头(6) + PDU(3) = 9字节
			if respLength != 3 || len(aduResponse) != 9 {
				return nil, GatewayRawData{RequestADU: aduRequest, ResponseADU: aduResponse, Error: err}, fmt.Errorf("invalid exception response format: PDU length=%d, ADU length=%d, expected PDU=3, ADU=9", respLength, len(aduResponse))
			}
			exceptionCode := aduResponse[8]
			return nil, GatewayRawData{RequestADU: aduRequest, ResponseADU: aduResponse, Error: err}, fmt.Errorf("gateway exception response: function 0x%02X, exception code 0x%02X",
				respFuncCode, exceptionCode)
		}

		// 验证正常响应的功能码
		if respFuncCode != request.FuncCode {
			if attempt < maxRetries {
				fmt.Printf("[Attempt %d/%d] Function code mismatch: got 0x%02X, expected 0x%02X, retrying in %v...\n",
					attempt, maxRetries, respFuncCode, request.FuncCode, retryDelay)
				time.Sleep(retryDelay)
				continue
			}
			return nil, GatewayRawData{RequestADU: aduRequest, ResponseADU: aduResponse, Error: err}, fmt.Errorf("function code mismatch after %d attempts", maxRetries)
		}

		// 构造响应结构
		response := &GatewayResponse{
			FuncCode: respFuncCode,
			SlaveID:  respUnitID,
			Data:     aduResponse[8:], // PDU数据部分（去掉MBAP头和功能码）
		}

		// fmt.Printf("[Attempt %d/%d] Gateway Response Success - FuncCode: 0x%02X, DataLength: %d\n",
		// 	attempt, maxRetries, response.FuncCode, len(response.Data))
		return response, GatewayRawData{RequestADU: aduRequest, ResponseADU: aduResponse, Error: nil}, nil
	}

	// 这里永远不会执行到，但为了代码完整性
	return nil, GatewayRawData{}, fmt.Errorf("unexpected error: exceeded retry loop")
}

// GetConnectionStatusName 获取连接状态名称
func GetConnectionStatusName(status uint8) string {
	if status == 0 {
		return "断开"
	}
	return "连接"
}

// isRetryableError 检查错误是否可重试
func isRetryableError(err error) bool {
	if err == nil {
		return false
	}

	errorStr := err.Error()

	// 网络错误检查
	if netErr, ok := err.(net.Error); ok {
		// 超时错误可重试
		if netErr.Timeout() {
			return true
		}
		// 临时错误可重试
		if netErr.Temporary() {
			return true
		}
	}

	// 检查常见的可重试错误消息
	return strings.Contains(errorStr, "timeout") ||
		strings.Contains(errorStr, "connection reset") ||
		strings.Contains(errorStr, "connection refused") ||
		strings.Contains(errorStr, "no route to host") ||
		strings.Contains(errorStr, "network unreachable") ||
		strings.Contains(errorStr, "broken pipe") ||
		strings.Contains(errorStr, "i/o timeout")
}

// 网关协议客户端API实现
/*
3.1.1.2 数据读取
•	请求指令长度固定7字节，固定读32条数据。
•	请求：功能码 0x50（1 字节）+32 位时间戳（4 字节）+ 记录条数 0x0020（2 字节）
•	响应：功能码 0x50（1 字节）+ 记录条数 0x0020（2 字节）+ 单记录字节数 0x10（1 字节）+512 字节数据。
•	单条 16 字节数据结构（共 32 条，总 512 字节）
*/
func (sf *client) GatewayReadDataRecords(slaveID byte, timestamp uint32) (records []*DataRecord, rawData GatewayRawData, err error) {
	// 构造请求数据：时间戳(4字节) + 记录条数(2字节)
	requestData := make([]byte, 6)
	binary.BigEndian.PutUint32(requestData[0:4], timestamp)
	binary.BigEndian.PutUint16(requestData[4:6], 32) // 记录条数=32

	// 构造网关请求
	request := &GatewayRequest{
		FuncCode: FuncCodeGatewayReadDataRecords, // 0x50
		SlaveID:  slaveID,
		Data:     requestData,
	}

	// 发送请求
	response, rawData, err := sf.sendGatewayRequest(request)
	if err != nil {
		return nil, rawData, fmt.Errorf("GatewayReadDataRecords failed: %v", err)
	}

	// 验证响应长度
	expectedLen := 3 + 512 // 3字节头部 + 512字节数据
	if len(response.Data) != expectedLen {
		return nil, rawData, errors.New("invalid response length for batch read")
	}

	// 解析响应头部
	recordCount := binary.BigEndian.Uint16(response.Data[0:2])
	if recordCount != 32 {
		return nil, rawData, errors.New("invalid record count in batch response")
	}

	if response.Data[2] != 16 {
		return nil, rawData, errors.New("invalid single record byte count in batch response")
	}

	// 解析32条数据记录
	records = make([]*DataRecord, 0, 32)
	dataOffset := 3
	for i := 0; i < 32; i++ {
		recordData := response.Data[dataOffset : dataOffset+16]
		record, err := NewDataRecordFromBytes(recordData)
		if err != nil {
			return nil, rawData, err
		}
		records = append(records, record)
		dataOffset += 16
	}

	return records, rawData, nil
}

func (sf *client) GatewayReadCurrentData(slaveID byte) (record *DataRecord, rawData GatewayRawData, err error) {
	// 构造请求数据：时间戳(4字节) + 记录条数(2字节)
	requestData := make([]byte, 6)
	binary.BigEndian.PutUint32(requestData[0:4], 0) // 时间戳=0表示当前时间
	binary.BigEndian.PutUint16(requestData[4:6], 1) // 记录条数=1

	// 构造网关请求
	request := &GatewayRequest{
		FuncCode: FuncCodeGatewayReadCurrentData, // 0x51
		SlaveID:  slaveID,                        // 从指定从站读取数据 01 02  03 04
		Data:     requestData,                    // 请求数据
	}

	// 发送请求
	response, rawData, err := sf.sendGatewayRequest(request)
	if err != nil {
		return nil, rawData, fmt.Errorf("GatewayReadCurrentData failed: %v", err)
	}

	// 验证响应数据长度：记录条数(2) + 单记录字节数(1) + 16字节数据 = 19字节
	if len(response.Data) != 19 {
		return nil, rawData, fmt.Errorf("invalid response data length: got %d, expected 19", len(response.Data))
	}

	// 解析响应头部
	recordCount := binary.BigEndian.Uint16(response.Data[0:2])
	if recordCount != 1 {
		return nil, rawData, fmt.Errorf("invalid record count: got %d, expected 1", recordCount)
	}

	if response.Data[2] != 16 {
		return nil, rawData, fmt.Errorf("invalid single record byte count: got %d, expected 16", response.Data[2])
	}

	// 解析数据记录
	recordData := response.Data[3:19]
	record, err = NewDataRecordFromBytes(recordData)
	if err != nil {
		return nil, rawData, fmt.Errorf("failed to parse data record: %v", err)
	}

	// fmt.Printf("GatewayReadCurrentData Success - Pressure: %.2f %s, Battery: %d%%, Time: %s\n",
	// 	record.Pressure, GetPressureUnitName(record.PressureUnit), record.BatteryLevel, record.GetTimeString())
	return record, rawData, nil
}

func (sf *client) GatewayWriteSubDevParam(slaveID byte, paramAddr uint16, paramValue uint32) (rawData GatewayRawData, err error) {
	// 验证Unit ID范围（变送器：1-64）
	if slaveID < 1 || slaveID > 64 {
		return rawData, errors.New("invalid Unit ID for sub-device, must be 1-64")
	}

	// 构造请求数据：参数地址(2字节) + 参数值(4字节)
	requestData := make([]byte, 6)
	binary.BigEndian.PutUint16(requestData[0:2], paramAddr)
	binary.BigEndian.PutUint32(requestData[2:6], paramValue)

	// 构造网关请求
	request := &GatewayRequest{
		FuncCode: FuncCodeGatewayWriteSubDevParam, // 0x52
		SlaveID:  slaveID,
		Data:     requestData,
	}

	// 发送请求
	response, rawData, err := sf.sendGatewayRequest(request)
	if err != nil {
		return rawData, fmt.Errorf("GatewayWriteSubDevParam failed: %v", err)
	}

	// 验证响应数据长度：参数地址(2) + 参数值(4) = 6字节
	if len(response.Data) != 6 {
		return rawData, fmt.Errorf("invalid response data length: got %d, expected 6", len(response.Data))
	}

	// 验证响应数据与请求一致（确认写入成功）
	respParamAddr := binary.BigEndian.Uint16(response.Data[0:2])
	respParamValue := binary.BigEndian.Uint32(response.Data[2:6])

	if respParamAddr != paramAddr || respParamValue != paramValue {
		return rawData, fmt.Errorf("response data mismatch: expected addr=0x%04X value=0x%08X, got addr=0x%04X value=0x%08X",
			paramAddr, paramValue, respParamAddr, respParamValue)
	}

	fmt.Printf("GatewayWriteSubDevParam Success - ParamAddr: 0x%04X, ParamValue: 0x%08X (%d)\n",
		respParamAddr, respParamValue, respParamValue)
	return rawData, nil
}

func (sf *client) GatewayWriteGatewayParam(slaveID byte, paramAddr uint16, paramValue uint32) (rawData GatewayRawData, err error) {
	// 验证Unit ID范围（网关：65-247）
	if slaveID < 1 || slaveID > 247 {
		return rawData, errors.New("invalid Unit ID for gateway, must be 1-247")
	}

	// 构造请求数据：参数地址(2字节) + 参数值(4字节)
	requestData := make([]byte, 6)
	binary.BigEndian.PutUint16(requestData[0:2], paramAddr)
	binary.BigEndian.PutUint32(requestData[2:6], paramValue)

	// 构造网关请求
	request := &GatewayRequest{
		FuncCode: FuncCodeGatewayWriteGWParam, // 0x53
		SlaveID:  slaveID,
		Data:     requestData,
	}

	// 发送请求
	response, rawData, err := sf.sendGatewayRequest(request)
	if err != nil {
		return rawData, fmt.Errorf("GatewayWriteGatewayParam failed: %v", err)
	}

	// 验证响应数据长度：参数地址(2) + 参数值(4) = 6字节
	if len(response.Data) != 6 {
		return rawData, fmt.Errorf("invalid response data length: got %d, expected 6", len(response.Data))
	}

	// 验证响应数据与请求一致（确认写入成功）
	respParamAddr := binary.BigEndian.Uint16(response.Data[0:2])
	respParamValue := binary.BigEndian.Uint32(response.Data[2:6])

	if respParamAddr != paramAddr || respParamValue != paramValue {
		return rawData, fmt.Errorf("response data mismatch: expected addr=0x%04X value=0x%08X, got addr=0x%04X value=0x%08X",
			paramAddr, paramValue, respParamAddr, respParamValue)
	}

	fmt.Printf("GatewayWriteGatewayParam Success - ParamAddr: 0x%04X, ParamValue: 0x%08X (%d)\n",
		respParamAddr, respParamValue, respParamValue)
	return rawData, nil
}

// 便捷方法：获取压力值的字符串表示
func (dr *DataRecord) GetPressureString() string {
	return fmt.Sprintf("%.2f %s", dr.Pressure, GetPressureUnitName(dr.PressureUnit))
}

// 便捷方法：获取时间的字符串表示
func (dr *DataRecord) GetTimeString() string {
	t := time.Unix(int64(dr.Timestamp), 0)
	return t.Format("2006-01-02 15:04:05")
}

// 便捷方法：判断设备是否在线
func (dr *DataRecord) IsDeviceOnline() bool {
	return dr.ConnectionStatus == 1
}

// 便捷方法：获取信号强度描述
func (dr *DataRecord) GetSignalStrengthDescription() string {
	switch dr.SignalLevel {
	case 0:
		return "无信号"
	case 1:
		return "信号弱"
	case 2:
		return "信号较弱"
	case 3:
		return "信号一般"
	case 4:
		return "信号良好"
	case 5:
		return "信号满格"
	default:
		return "未知"
	}
}

// GatewayReadSubDevParam 读子设备参数（功能码0x54）- 使用统一的ADU发送函数
func (sf *client) GatewayReadSubDevParam(slaveID byte, paramAddr uint16) (paramValue uint32, rawData GatewayRawData, err error) {
	// 构造请求数据：参数地址(2字节)
	requestData := make([]byte, 2)
	binary.BigEndian.PutUint16(requestData, paramAddr)

	// 构造网关请求
	request := &GatewayRequest{
		FuncCode: FuncCodeGatewayReadSubDevParam, // 0x54
		SlaveID:  slaveID,
		Data:     requestData,
	}

	// 发送请求
	response, rawData, err := sf.sendGatewayRequest(request)
	if err != nil {
		return 0, rawData, fmt.Errorf("GatewayReadSubDevParam failed: %v", err)
	}

	// 验证响应数据长度：参数地址(2) + 参数值(4) = 6字节
	if len(response.Data) != 6 {
		return 0, rawData, fmt.Errorf("invalid response data length: got %d, expected 6", len(response.Data))
	}

	// 解析响应数据：参数地址(2) + 参数值(4)
	respParamAddr := binary.BigEndian.Uint16(response.Data[0:2])
	respParamValue := binary.BigEndian.Uint32(response.Data[2:6])

	// 验证参数地址
	if respParamAddr != paramAddr {
		return 0, rawData, fmt.Errorf("parameter address mismatch: got 0x%04X, expected 0x%04X",
			respParamAddr, paramAddr)
	}

	fmt.Printf("GatewayReadSubDevParam Success - ParamAddr: 0x%04X, ParamValue: 0x%08X (%d)\n",
		respParamAddr, respParamValue, respParamValue)
	return respParamValue, rawData, nil
}

// GatewayReadGatewayParam 读网关参数（功能码0x55）- 使用统一的ADU发送函数
func (sf *client) GatewayReadGatewayParam(slaveID byte, paramAddr uint16) (paramValue uint32, rawData GatewayRawData, err error) {
	// 构造请求数据：参数地址(2字节)
	requestData := make([]byte, 2)
	binary.BigEndian.PutUint16(requestData, paramAddr)

	// 构造网关请求
	request := &GatewayRequest{
		FuncCode: FuncCodeGatewayReadGWParam, // 0x55
		SlaveID:  slaveID,
		Data:     requestData,
	}

	// 发送请求
	response, rawData, err := sf.sendGatewayRequest(request)
	if err != nil {
		return 0, rawData, fmt.Errorf("GatewayReadGatewayParam failed: %v", err)
	}

	// 验证响应数据长度：参数地址(2) + 参数值(4) = 6字节
	if len(response.Data) != 6 {
		return 0, rawData, fmt.Errorf("invalid response data length: got %d, expected 6", len(response.Data))
	}

	// 解析响应数据：参数地址(2) + 参数值(4)
	respParamAddr := binary.BigEndian.Uint16(response.Data[0:2])
	respParamValue := binary.BigEndian.Uint32(response.Data[2:6])

	// 验证参数地址
	if respParamAddr != paramAddr {
		return 0, rawData, fmt.Errorf("parameter address mismatch: got 0x%04X, expected 0x%04X",
			respParamAddr, paramAddr)
	}

	fmt.Printf("GatewayReadGatewayParam Success - ParamAddr: 0x%04X, ParamValue: 0x%08X (%d)\n",
		respParamAddr, respParamValue, respParamValue)
	return respParamValue, rawData, nil
}
